<?php
/**
 * Created by PhpStorm.
 * User: nightelf
 * Date: 2020/1/14
 * Time: 11:35
 */

namespace App\Http\Model;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class SupplierOrdersModel extends Model
{
    const TABLE = 'supplier_orders';
    const UNRECEIVED = 0;
    const RECEIVING = 1;
    const RECEIVED = 2;
    const COMPLETE = 3;

    public function addOrder(array $data)
    {
        DB::beginTransaction();
        try {
            if ($data['supplierId'] == 0) {
                $newSupplier = [
                    'name' => $data['name'],
                    'phone' => $data['phone'],
                    'address' => $data['address'],
                ];
                $data['supplierId'] = (new SupplierModel())->insert($newSupplier);
            }
            $totalPrice = 0;
            foreach ($data['data'] as $key => $d) {
                $totalPrice += $d['totalPrice'];
                $supplierOrdersInfoData[] = [
                    'materialId' => $d['materialId'],
                    'specId' => $d['specId'],
                    'supplierId' => $data['supplierId'],
                    'amount' => $d['amount'],
                    'price' => $d['price'],
                    'totalPrice' => $d['totalPrice'],
                    'unitId' => $d['unitId'],
                ];
            }
            //增加供应商货单记录
            $supplierOrder = [
                'supplierId' => $data['supplierId'],
                'projectId' => $data['projectId'],
                'totalPrice' => $totalPrice,
                'deliveryTime' => $data['deliveryTime'],
                'payType' => $data['payType'],
                'adminId' =>$data['adminId'],
                'remark' => $data['remark']
            ];
            if (empty($data['orderId'])){
                $supplierOrderId = $this->insert($supplierOrder);
                $supplierOrdersInfoModel = new SupplierOrdersInfoModel();
                foreach ($supplierOrdersInfoData as $k => $soi) {
                    $supplierOrdersInfoData[$k]['orderId'] = $supplierOrderId;
                    $supplierOrdersInfoData[$k]['materialsn'] = $supplierOrdersInfoModel->generateCode($soi['materialId']);
                }
                //更新
                if (!empty($supplierOrdersInfoData)) {
                    $supplierOrdersInfoModel->insert($supplierOrdersInfoData);
                }
            }else{
                DB::table('supplier_orders')->where('id',$data['orderId'])->update($supplierOrder);
                DB::table('supplier_orders_info')->where('orderId',$data['orderId'])->delete();
                $supplierOrdersInfoModel = new SupplierOrdersInfoModel();
                foreach ($supplierOrdersInfoData as $k => $soi) {
                    $supplierOrdersInfoData[$k]['orderId'] = $data['orderId'];
                    $supplierOrdersInfoData[$k]['materialsn'] = $supplierOrdersInfoModel->generateCode($soi['materialId']);
                }
                //更新
                if (!empty($supplierOrdersInfoData)) {
                    $supplierOrdersInfoModel->insert($supplierOrdersInfoData);
                }
            }


            DB::commit();
            return true;
        } catch (\Exception $e) {
            Log::info($e->getMessage() . ' in ' . $e->getFile() . '(' . $e->getLine() . ')');
//            DB::rollback();
//            return false;
        }
    }

    private function generateCode($projectId, $supplierId)
    {
        //4位项目编码+4位供应商编码+8位日期+5位货单顺序编码
        $projectCode = DB::table(ProjectModel::TABLE)->where('id', $projectId)->value('code');
        $supplierCode = DB::table(SupplierModel::TABLE)->where('id', $supplierId)->value('code');
        $date = date('Ymd');
        $lastCode = DB::table(self::TABLE)->orderBy('ordersn', 'desc')->where('projectId', $projectId)->value('ordersn');
        $number = intval(substr($lastCode, 16)) + 1;
        switch (strlen($number)) {
            case 1:
                $zeroFill = '0000';
                break;
            case 2:
                $zeroFill = '000';
                break;
            case 3:
                $zeroFill = '00';
                break;
            case 4:
                $zeroFill = '0';
                break;
            case 5:
                $zeroFill = '';
                break;
        }
        return $projectCode . $supplierCode . $date . $zeroFill . $number;
    }

    public function lists(array $data)
    {
        $limit = config('yucheng.limit');
        $start = 0;
        if (!empty($data['length'])) {
            $limit = $data['length'];
        }
        if (!empty($data['page'])) {
            $start = ($data['page'] - 1) * $limit;
        }
        $result = DB::table(self::TABLE)
            ->leftJoin('supplier as s', 's.id', '=', self::TABLE . '.supplierId')
            ->leftJoin('admin as a', 'a.id', '=', self::TABLE . '.adminId')
            ->where(function ($query) use ($data) {
                if (!empty($data['projectId'])) {
                    $query->where(self::TABLE . '.projectId', $data['projectId']);
                }
                if (!empty($data['supplierId'])) {
                    $query->where('supplierId', $data['supplierId']);
                }
                if (isset($data['status']) && $data['status'] != '') {
                    $query->where(self::TABLE . '.status', $data['status']);
                }
                if (isset($data['search']) && $data['search'] != '') {
                    $query->where('ordersn', 'like', '%' . $data['search'] . '%');
                }
                if (!empty($param['month'])) {
                    $startTime = (new \DateTime($param['month']))->format('Y-m-01 00:00:00');
                    $endTime = (new \DateTime($param['month']))->format('Y-m-t 23:59:59');
                    $query->whereBetween('deliveryTime', [$startTime, $endTime]);
                }
                if (!empty($data['startTime']) && !empty($data['endTime'])){
                    $query->whereBetween('deliveryTime',[$data['startTime'],$data['endTime']]);
                }
            })
//            ->orderBy('status')
            ->orderBy('deliveryTime','desc')
            ->offset($start)->limit($limit)
            ->select(self::TABLE . '.*', 's.name as supplierName','a.name as adminName')
            ->get()->toArray();
        return $result;
    }

    public function countLists(array $data)
    {
        return DB::table(self::TABLE)
            ->where(function ($query) use ($data) {
                if (!empty($data['projectId'])) {
                    $query->where('projectId', $data['projectId']);
                }
                if (!empty($data['supplierId'])) {
                    $query->where('supplierId', $data['supplierId']);
                }
                if (isset($data['status']) && $data['status'] != '') {
                    $query->where(self::TABLE . '.status', $data['status']);
                }
                if (isset($data['search']) && $data['search'] != '') {
                    $query->where('ordersn', 'like', '%' . $data['search'] . '%');
                }
                if (!empty($data['startTime']) && !empty($data['endTime'])){
                    $query->whereBetween('deliveryTime',[$data['startTime'],$data['endTime']]);
                }
            })
//            ->orderBy('status')
            ->count();
    }

    /**
     * @param array $data
     * @return array
     */
    public function info(array $data)
    {
        $result = DB::table(self::TABLE)->where($data)->first();
        return empty($result) ? [] : get_object_vars($result);
    }

    public function deleteOrder(array $param)
    {
        DB::beginTransaction();
        try {
            (new SupplierOrdersInfoModel())->delete(['orderId' => $param['id']]);
            DB::table(self::TABLE)->where($param)->delete();
            DB::commit();
        } catch (\Exception $e) {
            DB::rollback();
        }
    }

    /**
     * @param array $data
     * @return mixed
     */
    public function insert(array $data)
    {
        if ($data['payType'] == 1) {
            $data['isPay'] = 1;
        } else {
            $data['isPay'] = 0;
        }
        $data['ordersn'] = $this->generateCode($data['projectId'], $data['supplierId']);
        $data['createTime'] = date('Y-m-d H:i:s');
        return DB::table(self::TABLE)->insertGetId($data);
    }

    public function update(array $where, array $data)
    {
        return DB::table(self::TABLE)
            ->where(function ($query) use ($where) {
                if (!empty($where['id'])) {
                    $query->where('id', $where['id']);
                }
                if (!empty($where['supplierId'])) {
                    $query->where('supplierId', $where['supplierId']);
                }
                if (!empty($where['projectId'])) {
                    $query->where('projectId', $where['projectId']);
                }
                if (!empty($where['status'])) {
                    $query->where('status', $where['status']);
                }
                if (!empty($where['startTime']) && !empty($where['endTime'])) {
                    $query->whereBetween('deliveryTime', [$where['startTime'], $where['endTime']]);
                }
            })
            ->update($data);
    }

    public function receive(array $param)
    {
        DB::beginTransaction();
        try {
            $time = date('Y-m-d H:i:s');
            //收货记录及变更供应商订单已收货数量
            $supplierOrdersReceivingModel = new SupplierOrdersReceivingModel();
            $supplierOrdersReceivingInfoModel = new SupplierOrdersReceivingInfoModel();
            $supplierOrdersModel = new SupplierOrdersModel();
            $supplierOrdersInfoModel = new SupplierOrdersInfoModel();
            $warehouseModel = new WarehouseModel();
            $data1 = [
                'orderId' => $param['orderId'],
                'adminId' => $param['adminId'],
                'receivingTime' => $param['receivedTime'],
            ];
            $receivingId = $supplierOrdersReceivingModel->insert($data1);
            $data2 = [];
//            $allComplete = true;
            //构建出入库记录所需的数据
            $logData = [
                'projectId'=>$param['projectId'],
                'time'=>$param['receivedTime'],
                'remark' => '',
                'type' => WarehouseLogModel::PURCHASE,
                'adminId' => $param['adminId'],
                'price' =>0,
                'data' => [],
            ];
            foreach ($param['data'] as $d) {
                //订单记录、订单收货记录
                $info = $supplierOrdersInfoModel->info(['id' => $d['id']]);
                //构建收货明细的数据
                $data2[] = [
                    'receivingId' => $receivingId,
                    'orderId' => $param['orderId'],
                    'orderInfoId' => $d['id'],
                    'materialId' => $info['materialId'],
                    'specId' => $info['specId'],
                    'amount' => $d['received'],
                    'remark' => $d['remark'],
                ];
                $newQuantity = $info['receivedQuantity'] + $d['received'];
                if ($newQuantity >= $info['amount']) {
                    $status = self::RECEIVED;
                } else {
                    $status = self::RECEIVING;
                }
                //更新订单明细的收货数量和明细的收获状态
                $supplierOrdersInfoModel->update(['id' => $d['id']], [
                    'receivedQuantity' => $newQuantity,
                    'status' => $status,
                ]);
                //判断整个订单是否已经完成
//                if ($status != self::COMPLETE) {
//                    $allComplete = false;
//                }

                //库存记录
                //增加库存，检查仓库中是否有材料，增加库存
                $logData['price'] +=$d['received']*$info['price'];
                $warehouseData = [
                    'projectId' => $param['projectId'],
                    'materialId' => $info['materialId'],
                    'specId' => $info['specId'],
                ];
                $materialInfo = $warehouseModel->info($warehouseData);
                if (empty($materialInfo)) {
                    //创建仓库新的材料库存
                    $warehouseData = [
                        'projectId' => $param['projectId'],
                        'materialId' => $info['materialId'],
                        'specId' => $info['specId'],
                        'amount' => $d['received'],
                        'purchasePrice' => $info['price'],
                        'salePrice' => 0,
                        'unitId' => $info['unitId'],
                        'updateTime' => $time,
                    ];
                    (new WarehouseModel)->insert($warehouseData);
                    $surplus = $d['received'];
                } else {
                    $newPrice = ($materialInfo['amount'] * $materialInfo['purchasePrice'] + $d['received'] * $info['price']) / ($materialInfo['amount'] + $d['received']);
                    //更新库存
                    $settingModel = new SettingModel();
                    $saleRate = $settingModel->get('saleRate', $param['projectId']);
                    $salePrice = $newPrice * (1 + $saleRate);
                    $updateData = [
                        'amount' => $d['received'] + $materialInfo['amount'],
                        'purchasePrice' => $newPrice,
                        'salePrice' => $salePrice,
                        'updateTime' => $time,
                    ];
                    if (!$materialInfo['unitId']) {
                        $updateData['unitId'] = isset($info['unitId']) ? intval($info['unitId']) : 0;
                    }
                    //更新仓库库存数量及收储价格
                    $warehouseModel->update(['id' => $materialInfo['id']], $updateData);
                    $surplus = $d['received'] + $materialInfo['amount'];
                }
                //构建出入库记录所需的数据
                $logData['data'][] = [
                    'materialId' => $info['materialId'],
                    'specId' => $info['specId'],
                    'supplierId' => $info['supplierId'],
                    'amount' => $d['received'],
                    'price' => $info['price'],
                    'totalPrice' => $d['received']*$info['price'],
                    'unitId' => $info['unitId'],
                    'surplus' => $surplus,
                    'remark' => $d['remark'],
                ];
            }
            //如果整个订单完成，则更新整个订单的收获状态
            $supplierOrdersModel->update(['id' => $param['orderId']], ['status' => self::RECEIVING]);
            //插入收货明细
            $supplierOrdersReceivingInfoModel->insert($data2);
            //插入日志
            $r = (new WarehouseLogModel)->addLog($logData);
            DB::commit();
        } catch (\Exception $e) {
            Log::info('Error:'. $e->getMessage() . ' at '.$e->getFile() . ' line:'.$e->getLine().'\n'.$e->getTraceAsString());
            DB::rollback();
        }
    }

    public function received(array $param){
        DB::beginTransaction();
        try{
            $this->update($param,['status'=>self::RECEIVED]);
            (new SupplierOrdersInfoModel())->update(['orderId'=>$param['id']],['status'=>self::RECEIVED]);
            DB::commit();
        }catch(\Exception $e){
            DB::rollback();
        }
    }

    ///////////////////////////////////////////////////

    /**
     * 货单总金额
     * @param array $data
     * @return
     */
    public function getSum(array $data)
    {
        return DB::table(self::TABLE)
            ->where(function ($query) use ($data) {
                if (isset($data['isPay'])) {
                    $query->where('isPay', $data['isPay']);
                }
                if (!empty($data['startTime']) && !empty($data['endTime'])) {
                    $query->whereBetween('deliveryTime', [$data['startTime'],$data['endTime']]);
                }
                if (!empty($data['projectId'])) {
                    $query->where('projectId', $data['projectId']);
                }
                if (!empty($data['supplierId'])) {
                    $query->where('supplierId', $data['supplierId']);
                }
            })
            ->sum('totalPrice');
    }

    /**
     * @param array $data
     * @return array
     * @throws \Exception
     */
    public function accountsPerMonth(array $data)
    {
        $months = $this->datePeriod($data['startTime'], date('Y-m-d H:i:s'), '1 month', 'Y-m');
        $result = [];
        foreach ($months as $key => $month) {
            $tmp['time'] = $key;
            $tmp['ordersSum'] = $this->getSum(['startTime' => date('Y-m-01 00:00:00', strtotime($key)),
                'endTime' => date('Y-m-t 23:59:59', strtotime($key)), 'supplierId' => $data['supplierId'], 'projectId' => $data['projectId']]);
            //已付货单金额
            $tmp['paySum'] = $this->getSum(['startTime' => date('Y-m-01 00:00:00', strtotime($key)),
                'endTime' => date('Y-m-t 23:59:59', strtotime($key)), 'isPay' => 1, 'supplierId' => $data['supplierId'], 'projectId' => $data['projectId']]);
            //实际付款金额
            $tmp['unpaySum'] = $this->getSum(['startTime' => date('Y-m-01 00:00:00', strtotime($key)),
                'endTime' => date('Y-m-t 23:59:59', strtotime($key)), 'isPay' => 0, 'supplierId' => $data['supplierId'], 'projectId' => $data['projectId']]);
            $result[] = $tmp;
        }
        return array_reverse($result);
    }

    public function listPerMonth(array $data)
    {
        $result = DB::table(self::TABLE)
            ->leftJoin('supplier as s', 's.id', '=', self::TABLE . '.supplierId')
            ->leftJoin('admin as a', 'a.id', '=', self::TABLE . '.adminId')
            ->where(function ($query) use ($data) {
                if (!empty($data['projectId'])) {
                    $query->where(self::TABLE.'.projectId', $data['projectId']);
                }
                if (!empty($data['supplierId'])) {
                    $query->where('supplierId', $data['supplierId']);
                }
                if (isset($data['status']) && $data['status'] != '') {
                    $query->where(self::TABLE . '.status', $data['status']);
                }
                if (isset($data['search']) && $data['search'] != '') {
                    $query->where('ordersn', 'like', '%' . $data['search'] . '%');
                }
                if (!empty($data['month'])) {
                    $startTime = (new \DateTime($data['month']))->format('Y-m-01 00:00:00');
                    $endTime = (new \DateTime($data['month']))->format('Y-m-t 23:59:59');
                    $query->whereBetween('deliveryTime', [$startTime, $endTime]);
                }
            })
            ->orderBy('status')
            ->select(self::TABLE . '.*', 's.name as supplierName','a.name as adminName')
            ->get()->toArray();
        return $result;
    }

    /**
     * @param array $param
     */
    public function complete(array $param)
    {
        DB::beginTransaction();
        try{
            $this->update($param,['status'=>self::COMPLETE]);
            (new SupplierOrdersInfoModel())->update(['orderId'=>$param['id']],['status'=>self::COMPLETE]);
            DB::commit();
        }catch(\Exception $e){
            DB::rollback();
        }
    }
}